package at.codebase.web.servlets.item;

import static at.codebase.web.util.i18n.I18NFactory.i18n;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

import org.json.simple.JSONObject;

import at.codebase.core.search.SearchItem;
import at.codebase.db.dao.EApiPartnerDao;
import at.codebase.db.dao.EExternalItemFeedbackDao;
import at.codebase.db.entities.EApiPartner;
import at.codebase.db.entities.EExternalItemFeedback;
import at.codebase.db.entities.EItemFeedback.EItemFeedbackRating;
import at.codebase.security.SecureStringBuilder;
import at.codebase.web.servlets.item.ItemInputStatus.InputStatus;
import at.codebase.web.servlets.item.ItemInputStatus.InputStatusFeedbackRating;
import at.codebase.web.servlets.item.ItemInputStatus.InputStatusFeedbackText;
import at.codebase.web.servlets.item.ItemInputStatus.InputStatusVoid;
import at.codebase.web.templates.ErrorWidget;
import at.codebase.web.templates.ExternItemDetailsFeedback;
import at.codebase.web.templates.MainTemplate;
import at.codebase.web.templates.RubyRatingBar;
import at.codebase.web.util.LocalRequest.RequestInformation;
import at.codebase.web.util.URLParameters.ParameterDoesNotExistException;
import at.codebase.web.util.URLParameters.ParameterException;
import at.codebase.web.util.api.ApiPartnerCalls;
import at.codebase.web.util.json.JsonKeys;
import at.codebase.web.util.servlet.SecureServlet;
import at.codebase.web.util.template.Template;
import at.codebase.web.util.template.TemplateEngine;

import com.google.appengine.api.search.GeoPoint;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

@SuppressWarnings("rawtypes")
public class MinimumItemDetails extends SecureServlet {
	static HashMap<String, InputStatus> emptyInputStatusMap = new HashMap<String, InputStatus>();

	static {
		emptyInputStatusMap.put("feedbackRating", new InputStatusVoid());
		emptyInputStatusMap.put("feedbackText", new InputStatusVoid());
	}
	
	private class FeedbackData {
		boolean userAlreadyRated;
		List<EExternalItemFeedback> itemFeedbackList;
		double ratingAverage;
		int ratingTotal;
	}
	
	@Override
	protected void initSecurityLevels(ArrayList<UserLevel> secLevels) {
		secLevels.add(UserLevel.ANONYMOUS);
		secLevels.add(UserLevel.REGISTERED);
		secLevels.add(UserLevel.ADMIN);
	}
	
	@Override
	protected RequestType requestType() {
		return RequestType.POST_AND_GET;
	}

	@Override
	protected void processRequestSecurityLevel(
			RequestInformation requestInfo, UserLevel level,
			RequestType requestType) {
		Long partnerId = null;
		String itemId = null;
		try {
			partnerId = new Long(requestInfo.getParameters().getString("partnerId"));
			itemId = requestInfo.getParameters().getString("itemId");
		} catch (NumberFormatException e1) {
			// TODO Auto-generated catch block
		} catch (ParameterDoesNotExistException e1) {
			// TODO Auto-generated catch block
		}
		
		MainTemplate mainTemplate = new MainTemplate(requestInfo, writer());
		mainTemplate.addJSScript("script_item_details_external.js");
		
		if(itemId == null || partnerId == null) {
			show404NotFound(mainTemplate, requestInfo);
			return;
		}
		EApiPartner partner = EApiPartnerDao.getApiPartner(partnerId);
		JSONObject obj = ApiPartnerCalls.getItem(partner, 
				itemId);
		if(obj != null && obj.get("itemId") != null) {
			itemId = obj.get("itemId").toString();
		}
		if(itemId == null) {
			itemId = obj.get("id").toString();
		}
		if(itemId != null) {
			SearchItem item = new SearchItem();
			item.setItemId(itemId);
			item.setTitle((String) obj.get("title"));
			item.setPrice((String) obj.get("price"));
			item.setUrl((String) obj.get("url"));
			item.setDescription((String)obj.get("description"));
			JSONObject sellerObj = (JSONObject) obj.get("seller");
			item.setSellerId(sellerObj.get("id").toString());
			item.setSellerName((String) sellerObj.get("username"));
			String image = (String) obj.get(JsonKeys.IMAGE);
			if (image != null && !image.isEmpty()) {
				item.setImage((String) obj.get(JsonKeys.IMAGE));
			}
			Object location = obj.get(JsonKeys.LOCATION);
			if (location != null) {
				item.setLocation((GeoPoint) location);
			}
			//Feedback
			FeedbackData feedbackData = new FeedbackData();
			feedbackData.userAlreadyRated = false;
			feedbackData.itemFeedbackList = EExternalItemFeedbackDao.getFeedbackByItem(partnerId, itemId);
			double ratingSum = 0;
			for(EExternalItemFeedback itemFeedback:feedbackData.itemFeedbackList){
				if(itemFeedback != null){
					if(requestInfo.isUserLoggedIn() && itemFeedback.getLocalUserId().equals(requestInfo.getUser().getId())){
						feedbackData.userAlreadyRated = true;
					}
					ratingSum += itemFeedback.getFeedbackRatingValue();
					feedbackData.ratingTotal++;
				}
			}
			feedbackData.ratingAverage = ratingSum / ((double)feedbackData.ratingTotal);

			System.out.println("itemId found");
			if(requestInfo.isUserLoggedIn() && !feedbackData.userAlreadyRated){
				if(requestType.equals(RequestType.POST)){
					if(!tokenCorrect(requestInfo)) {
						processRequestNoAccess(requestInfo, level);
						return;
					}
					HashMap<String, InputStatus> inputStatusMap = new HashMap<String, InputStatus>();
					
					try {
						inputStatusMap.put("feedbackRating", new InputStatusFeedbackRating(requestInfo.getParameters().getString("feedbackRating")));
					} catch (ParameterException e) {
						inputStatusMap.put("feedbackRating", new InputStatusFeedbackRating(null));
					}
					
					try {
						inputStatusMap.put("feedbackText", new InputStatusFeedbackText(requestInfo.getParameters().getString("feedbackText")));
					} catch (ParameterException e) {
						inputStatusMap.put("feedbackText", new InputStatusFeedbackText(null));
					}
					
					boolean allValid = true;
					
					for(String key:inputStatusMap.keySet()){
						InputStatus inputStatus = inputStatusMap.get(key);
						inputStatus.compile();
						if(inputStatus.isError())
							allValid = false;
					}
						
					if(allValid){
						//Save Feedback
						EItemFeedbackRating feedbackRating = ((InputStatusFeedbackRating) inputStatusMap.get("feedbackRating")).getValue();
						String feedbackText = ((InputStatusFeedbackText) inputStatusMap.get("feedbackText")).getValue();
						EExternalItemFeedback itemFeedback = EExternalItemFeedback.create(item.getItemId(), requestInfo.getUser().getId(), feedbackRating, feedbackText);
						itemFeedback.setPartnerId(partnerId);
						itemFeedback.setLocalUserId(requestInfo.getUser().getId());
						itemFeedback.setLocalUsername(requestInfo.getUser().getUsername());
						itemFeedback.setTimeCreate(new Long(System.currentTimeMillis()));
						EExternalItemFeedbackDao.addItemFeedback(itemFeedback);
						ApiPartnerCalls.submitItemRating(partner, itemFeedback.getItemId(), requestInfo.getUser().getUsername(), 
								requestInfo.getUser().getId(), feedbackRating, feedbackText, itemFeedback.getId());;
						redirectTo("/item/extern/"+String.valueOf(partnerId) + "/" +item.getItemId());
					}else{
						// Show the Item Details
						buildPage(mainTemplate, requestInfo, level, item, partnerId, inputStatusMap, feedbackData);
					}
				}else{
					// Show the Item Details
					buildPage(mainTemplate, requestInfo, level, item, partnerId, emptyInputStatusMap, feedbackData);
				}
			}else{
				// Show the Item Details
				buildPage(mainTemplate, requestInfo, level, item, partnerId, emptyInputStatusMap, feedbackData);	
			}
		}else{
			//Show Not Found Error (Because Item is not active)
			show404NotFound(mainTemplate, requestInfo);
		}
		mainTemplate.render(requestInfo.getLocale());
	}
	
		
	private void buildPage(MainTemplate mainTemplate, RequestInformation requestInfo, UserLevel level, SearchItem item, Long partnerId, HashMap<String, InputStatus> inputStatusMap, FeedbackData feedbackData){
	
		Template itemDetails = TemplateEngine.getTemplate("item/site_details_item.html");
		
		//Load Images
		SecureStringBuilder imageListString = new SecureStringBuilder();
		String imageUrl = item.getImage();
		int numImages = 0;
		if(imageUrl != null && !imageUrl.isEmpty()){
			numImages = 1;
			imageListString.appendInsecure("<img id=\"imageId0\" class=\"itemDetailsImage\" src=\"" + imageUrl + "\">");
		}else{
			imageListString.appendInsecure("<img class=\"itemDetailsImage\" src=\"/images/no_image_available.png\">");
		}
		itemDetails.setHTML("imageList", imageListString.toString());
		itemDetails.setText("imagesTotal", String.valueOf(numImages));
		
		itemDetails.setText("itemId", item.getItemId());
		itemDetails.setText("itemTitle", item.getTitle());

		itemDetails.setText("itemPrice", item.getPrice());

		itemDetails.setText("itemDescription", item.getDescription());
		itemDetails.setText("itemSeller", item.getSellerName());
		itemDetails.setTemplate("itemRatingRubyBar", new RubyRatingBar(feedbackData.ratingAverage, feedbackData.ratingTotal));
		
		//Feedback
		ArrayList<Template> feedbackTemplates = new ArrayList<Template>();
	
		Comparator<EExternalItemFeedback> newestFirstComparator = new Comparator<EExternalItemFeedback>() {
			@Override
			public int compare(EExternalItemFeedback o1, EExternalItemFeedback o2) {
				if(o1.getTimeCreate().longValue() < o2.getTimeCreate().longValue()){
					return 1;
				}else if(o1.getTimeCreate().longValue() > o2.getTimeCreate().longValue()){
					
					return -1;
				}else{
					return 0;
				}
			}
		};
		Collections.sort(feedbackData.itemFeedbackList, newestFirstComparator);
		for(EExternalItemFeedback itemFeedback:feedbackData.itemFeedbackList){
			if(itemFeedback != null){
				ExternItemDetailsFeedback feedbackContainer = new ExternItemDetailsFeedback(requestInfo, level, itemFeedback);
				feedbackTemplates.add(feedbackContainer);
			}
		}
		if(feedbackTemplates.size()>0){
			itemDetails.setTemplates("itemFeedbackList", feedbackTemplates);
		}else{
			itemDetails.setHTML("itemFeedbackList", "<div class=\"itemDetailsFeedbackNothing\">"+i18n(requestInfo.getLocale()).string("itemDetails_feedback_nothing")+"</div>");
		}
		
		/*
		 * Admin Menu
		 */
		if(level.equals(UserLevel.ADMIN)){
			Template adminMenu = TemplateEngine.getTemplate("item/site_details_external_menu_admin.html");
			adminMenu.setText("randomKey", nextToken());
			adminMenu.setText("itemId", String.valueOf(item.getItemId()));
			itemDetails.setTemplate("itemAdminMenu", adminMenu);
		}
		if(requestInfo.isUserLoggedIn()){
			/*
			 * Customer Menu
			 */
				Template customerMenu = TemplateEngine.getTemplate("item/site_details_extern_menu_customer.html");
				customerMenu.setText("sellerId", item.getSellerId().toString());
				customerMenu.setText("itemId", item.getItemId());
				customerMenu.setText("partnerId", partnerId.toString());
				itemDetails.setTemplate("itemCustomerMenu", customerMenu);
				
				//Costumer Feedback
				Template giveFeedbackT = TemplateEngine.getTemplate("item/site_details_give_extern_feedback.html");	
				giveFeedbackT.setText("randomKey", nextToken());
				giveFeedbackT.setText("itemId", item.getItemId());
				giveFeedbackT.setText("partnerId", partnerId.toString());
				
				//ErrorWidget
				ErrorWidget errorWidget = new ErrorWidget();
				if(inputStatusMap.get("feedbackRating").isError())
					errorWidget.addErrorItem(i18n(requestInfo.getLocale()).string("itemDetails_giveFeedback_errorRating"));
				if(inputStatusMap.get("feedbackText").isError())
					errorWidget.addErrorItem(i18n(requestInfo.getLocale()).string("itemDetails_giveFeedback_errorText"));
				
				if(errorWidget.hasErrors())
					giveFeedbackT.setTemplate("errorWidget", errorWidget);
				
				giveFeedbackT.setHTML("feedbackRatingValue", new SecureStringBuilder().appendSecure(inputStatusMap.get("feedbackRating").getRawString()).toString());
				giveFeedbackT.setHTML("feedbackTextValue", new SecureStringBuilder().appendSecure(inputStatusMap.get("feedbackText").getRawString()).toString());

				if(!feedbackData.userAlreadyRated){
					itemDetails.setTemplate("giveFeedback", giveFeedbackT);
				}else{
					itemDetails.setHTML("giveFeedback", "<div class=\"itemDetailsGiveFeedbackAlreadyRated\">"+i18n(requestInfo.getLocale()).string("itemDetails_giveFeedback_alreadyRated")+"</div>");
				}
		}else{
			Template anonCustomerMenu = TemplateEngine.getTemplate("item/site_details_menu_anonymous.html");
			UserService userService = UserServiceFactory.getUserService();
			anonCustomerMenu.setHTML("loginUrl", userService.createLoginURL("/user/profile"));
			itemDetails.setTemplate("itemCustomerMenu", anonCustomerMenu);
		}

		if(item.getLocation() != null) {
			//Item Details
			itemDetails.setText("locationLatitude", String.valueOf(item.getLocation().getLatitude()));
			itemDetails.setText("locationLongitude", String.valueOf(item.getLocation().getLatitude()));
		} else {
			itemDetails.setText("googleMap", "");
		}
		mainTemplate.setTemplate("body", itemDetails);
	}
	
	private void show404NotFound(MainTemplate mainTemplate, RequestInformation requestInfo){
		mainTemplate.setTitle(i18n(requestInfo.getLocale()).string("itemDetails_error_notFound_title"));
		Template notFoundItemTemplate = TemplateEngine.getTemplate("item/error_not_found_item.html");
		mainTemplate.setTemplate("body", notFoundItemTemplate);
	}

	@Override
	protected void processRequestNoAccess(RequestInformation requestInfo,
			UserLevel level) {

	}

}
